package com.wanghengzhi.girlfriend.rbac.module.account;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Profile;
import org.springframework.restdocs.RestDocumentationContextProvider;
import org.springframework.restdocs.RestDocumentationExtension;
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
import org.springframework.restdocs.payload.FieldDescriptor;
import org.springframework.restdocs.payload.JsonFieldType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;

/**
 * 测试共用类。
 * @author 王潇
 * @since 2021.6.17
 */
@SuppressWarnings("all")
@ActiveProfiles("test")
@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
public class ControllerParent {

    protected MockMvc mockMvc;

    protected RestDocumentationResultHandler documentationResultHandler;

    @Autowired
    protected ObjectMapper jacksonMapper;

    /**
     * 公共的返回信息
     */
    protected FieldDescriptor[] commonResponse;

    /**
     * 分页返回信息
     */
    protected FieldDescriptor[] pageResponse;

    /**
     * 设置rest-doc 配置，并初始化 documentationResultHandler ， 用来编写文档（子类）
     * @param webApplicationContext spring context
     * @param restDocumentation restDocument
     */
    @BeforeEach
    public void setUp(WebApplicationContext webApplicationContext,
                      RestDocumentationContextProvider restDocumentation) {
        this.documentationResultHandler = document("{class-name}/{method-name}");
        this.mockMvc = MockMvcBuilders
                .webAppContextSetup(webApplicationContext)
                .apply(documentationConfiguration(restDocumentation)
                        .operationPreprocessors()
                        .withRequestDefaults(prettyPrint())
                        .withResponseDefaults(prettyPrint())
                )
                .alwaysDo(documentationResultHandler)
                .build();

        this.commonResponse = new FieldDescriptor[]{
                fieldWithPath("ok").type(JsonFieldType.BOOLEAN).description("本次请求是否达到预期结果。"),
                fieldWithPath("message").type(JsonFieldType.STRING).description("成功或失败提示信息。"),
        };

        this.pageResponse = new FieldDescriptor[]{
                fieldWithPath("page").type(JsonFieldType.NUMBER).description("页码"),
                fieldWithPath("size").type(JsonFieldType.NUMBER).description("数量"),
                fieldWithPath("totalPages").type(JsonFieldType.NUMBER).description("总页数"),
                fieldWithPath("totalElements").type(JsonFieldType.NUMBER).description("总数量"),
                fieldWithPath("isFirst").type(JsonFieldType.BOOLEAN).description("是否第一页"),
                fieldWithPath("isLast").type(JsonFieldType.BOOLEAN).description("是否最后一页"),
                fieldWithPath("hasNext").type(JsonFieldType.BOOLEAN).description("是否有下一页"),
                fieldWithPath("hasPrevious").type(JsonFieldType.BOOLEAN).description("是否有上一页"),
                fieldWithPath("contents").type(JsonFieldType.ARRAY).description("页码")
        };
    }

    /**
     * 设置perform执行结果字符集，默认是iso-8891，中文显示会乱码。
     * @param ResultActions http返回对象
     */
    protected void setUTF8(ResultActions perform) {
        perform.andReturn().getResponse().setCharacterEncoding("utf-8");
    }

}
